#pragma once

#include <memory>
#include <vector>

struct Node;
struct Expr;
struct Query;
struct JoinExpr;
struct FromExpr;
struct RangeTblRef;
struct RangeTblEntry;
struct SetOperationStmt;

namespace optimizer {
class Operator;

/**
 * Transform a query from parsed statement to operator expressions.
 */
class QueryToOperatorTransformer {
 public:
  QueryToOperatorTransformer() = default;

  std::shared_ptr<Operator> TransformQuery(Query* query);

 private:
  std::shared_ptr<Operator> TransformSelectQuery(Query* query);

  std::shared_ptr<Operator> VisitNode(Node* node);

  std::shared_ptr<Operator> Visit(SetOperationStmt* set);
  std::shared_ptr<Operator> Visit(RangeTblRef* table);
  std::shared_ptr<Operator> Visit(FromExpr* from);
  std::shared_ptr<Operator> Visit(JoinExpr* join);

  Query* PreProcessQuery(Query* query);

  std::vector<Query*> processing_queries_;
  bool recorder_agg_exprs_{false};
};

}  // namespace optimizer
